#include "adc_dma.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_dma.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#define SAMPLE_COUNT (5)   // 缓存深度

// ADC转换值存储（DMA传输目标）
static uint16_t adc_values[ADC_CHANNEL_COUNT * SAMPLE_COUNT];      // 原始值
static uint16_t adc_count_buff[ADC_CHANNEL_COUNT][SAMPLE_COUNT];   // 缓存区
static uint16_t adc_buffer[ADC_CHANNEL_COUNT];                     // 滤波后

// ADC配置
ADC_Config_t adc_config = {
    .ADCx              = ADC1,
    .DMAy_Channelx     = DMA1_Channel1,
    .ADC_Channels      = {ADC_Channel_12, ADC_Channel_13, ADC_Channel_14},   // PC2, PC3, PC4
    .ADC_Channel_Count = ADC_CHANNEL_COUNT,
    .sample_time       = ADC_SampleTime_55Cycles5,
    .continuous_mode   = false};

// ADC DMA初始化函数
void ADC_DMA_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef  ADC_InitStructure;
    DMA_InitTypeDef  DMA_InitStructure;

    // 使能GPIOC、ADC1和DMA1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_ADC1, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    // 配置PC2、PC3、PC4为模拟输入
    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    // DMA1通道1配置（ADC1使用DMA1通道1）
    DMA_DeInit(adc_config.DMAy_Channelx);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &adc_config.ADCx->DR;
    DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t) adc_values;
    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize         = ADC_CHANNEL_COUNT * SAMPLE_COUNT;
    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;   // 循环模式
    DMA_InitStructure.DMA_Priority           = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;
    DMA_Init(adc_config.DMAy_Channelx, &DMA_InitStructure);

    // 使能DMA
    DMA_Cmd(adc_config.DMAy_Channelx, ENABLE);

    // ADC1配置
    ADC_InitStructure.ADC_Mode               = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode       = ENABLE;   // 扫描模式
    ADC_InitStructure.ADC_ContinuousConvMode = adc_config.continuous_mode ? ENABLE : DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv   = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel       = adc_config.ADC_Channel_Count;

    ADC_Init(adc_config.ADCx, &ADC_InitStructure);

    // 配置ADC通道的转换顺序和采样时间
    for (uint8_t i = 0; i < adc_config.ADC_Channel_Count; i++) {
        ADC_RegularChannelConfig(adc_config.ADCx,
                                 adc_config.ADC_Channels[i],
                                 i + 1,
                                 adc_config.sample_time);
    }

    // 使能ADC的DMA
    ADC_DMACmd(adc_config.ADCx, ENABLE);

    // 使能ADC
    ADC_Cmd(adc_config.ADCx, ENABLE);

    // ADC校准
    ADC_Calibrate();
    ADC_StartConversion();
    ADC_SetContinuousMode(true);
    ADC_SetSampleTime(ADC_SampleTime_239Cycles5);
}

// 获取指定ADC通道的值
uint16_t ADC_GetChannelValue(ADC_Channel_t channel) {
    if (channel >= ADC_CHANNEL_MAX) {
        return 0;
    }
    return adc_values[channel];
}

// 启动ADC转换
void ADC_StartConversion(void) {
    ADC_SoftwareStartConvCmd(adc_config.ADCx, ENABLE);
}

// 停止ADC转换
void ADC_StopConversion(void) {
    ADC_SoftwareStartConvCmd(adc_config.ADCx, DISABLE);
}

// 设置ADC采样时间
void ADC_SetSampleTime(uint8_t sample_time) {
    adc_config.sample_time = sample_time;

    // 重新配置所有通道的采样时间
    for (uint8_t i = 0; i < adc_config.ADC_Channel_Count; i++) {
        ADC_RegularChannelConfig(adc_config.ADCx,
                                 adc_config.ADC_Channels[i],
                                 i + 1,
                                 adc_config.sample_time);
    }
}

// 设置连续转换模式
void ADC_SetContinuousMode(bool enable) {
    adc_config.continuous_mode = enable;

    // 重新配置ADC
    ADC_InitTypeDef ADC_InitStructure;
    ADC_InitStructure.ADC_Mode               = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode       = ENABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = adc_config.continuous_mode ? ENABLE : DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv   = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign          = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel       = adc_config.ADC_Channel_Count;

    ADC_Init(adc_config.ADCx, &ADC_InitStructure);
}

// ADC校准
void ADC_Calibrate(void) {
    // 重置校准寄存器
    ADC_ResetCalibration(adc_config.ADCx);
    while (ADC_GetResetCalibrationStatus(adc_config.ADCx))
        ;

    // 开始校准
    ADC_StartCalibration(adc_config.ADCx);
    while (ADC_GetCalibrationStatus(adc_config.ADCx))
        ;
}
// 获取滤波后AD值
uint16_t Read_adc_value(uint8_t CHANNEL) {
    for (uint8_t i = 0; i < SAMPLE_COUNT; i++) {
        adc_count_buff[CHANNEL][i] = adc_values[i * ADC_CHANNEL_COUNT + CHANNEL];
    }

    adc_buffer[CHANNEL] = Improved_aver_filter(&adc_count_buff[CHANNEL][0], SAMPLE_COUNT, 1);
    return adc_buffer[CHANNEL];
}
// 滤波
uint16_t Improved_aver_filter(uint16_t* buffer, uint8_t count, uint8_t trim_count) {
    uint32_t sum     = 0;
    uint16_t min_val = 0xFFFF;
    uint16_t max_val = 0;
    if (count <= 2 * trim_count) {   // 如果trim_count太大，直接返回原始值
        return buffer[0];
    }
    // 一次遍历找到最小值和最大值
    for (uint8_t i = 0; i < count; i++) {
        sum += buffer[i];
        if (buffer[i] < min_val) {
            min_val = buffer[i];
        }
        if (buffer[i] > max_val) {
            max_val = buffer[i];
        }
    }

    // 减去最小值和最大值（去极值）
    sum = sum - min_val - max_val;

    // 计算平均值
    return (uint16_t) (sum / (count - 2));
}
